#include "ldg_i2c.h"

void initI2CGpio()
{
  gpio_set_pull_mode(GPIO_I2C_SDA, GPIO_PULLUP_ONLY);
  gpio_set_pull_mode(GPIO_I2C_SCL, GPIO_PULLUP_ONLY);
}
esp_err_t ldg_i2c_master_init()
{
  initI2CGpio();
  i2c_config_t conf = {
      .mode = I2C_MODE_MASTER,
      .sda_io_num = GPIO_I2C_SDA,
      .sda_pullup_en = GPIO_PULLUP_ENABLE,
      .scl_io_num = GPIO_I2C_SCL,
      .scl_pullup_en = GPIO_PULLUP_ENABLE,
      .master.clk_speed = I2C_MASTER_FREQ_HZ,
  };
  esp_err_t ret = i2c_param_config(I2C_MASTER_NUM, &conf);
  if (ret != ESP_OK)
  {
    ESP_LOGE("I2C主机", "I2C主机初始化错误");
    return ret;
  }

  ret = i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER, 0, 0, 0);
  if (ret != ESP_OK)
  {
    ESP_LOGE("I2C主机", "I2C驱动安装错误");
    return ret;
  }
  return ret;
}

ParseResult ldg_i2c_master_read_data2(uint8_t slave_address, uint16_t data_length)
{
  ESP_LOGI("I2C主机", "读取数据，长度: %d", data_length);
  ParseResult result;
  result.status = ESP_FAIL;

  WORD_ALIGNED_ATTR uint8_t *data_rd = (uint8_t *)malloc(data_length);
  memset(data_rd, 0xFF, data_length);

  esp_err_t ret = ldg_i2c_master_init();
  if (ret != ESP_OK)
  {
    return result;
  }
  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  i2c_master_start(cmd);
  i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, true);
  i2c_master_read(cmd, data_rd, data_length, I2C_MASTER_LAST_NACK);
  i2c_master_stop(cmd);
  ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
  if (ret != ESP_OK)
  {
    ESP_LOGE("I2C主机", "I2C主机命令执行出错，代码: %d", ret);
    return result;
  }
  i2c_cmd_link_delete(cmd);
  i2c_driver_delete(I2C_MASTER_NUM);
  esp_log_buffer_hex_internal("I2C主机,读取结果", data_rd, data_length, ESP_LOG_INFO);
  result.status = ret;
  result.data = data_rd;
  return result;
}

ParseResult ldg_i2c_master_read(uint8_t slave_address, uint8_t *read_cmd, uint8_t cmd_length, uint16_t data_length)
{
  esp_log_buffer_hex_internal("I2C主机,读取地址", read_cmd, cmd_length, ESP_LOG_INFO);
  ParseResult result;
  result.status = ESP_FAIL;
  WORD_ALIGNED_ATTR uint8_t *data_rd = (uint8_t *)malloc(data_length);
  memset(data_rd, 0xFF, data_length);
  esp_err_t ret = ldg_i2c_master_init();
  if (ret != ESP_OK)
  {
    return result;
  }
  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  i2c_master_start(cmd);
  i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, true);
  for (size_t i = 0; i < cmd_length; i++)
  {
    i2c_master_write_byte(cmd, read_cmd[i], true);
  }
  i2c_master_start(cmd);
  i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_READ, true);
  i2c_master_read(cmd, data_rd, data_length, I2C_MASTER_LAST_NACK);
  i2c_master_stop(cmd);
  ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
  if (ret != ESP_OK)
  {
    ESP_LOGE("I2C主机", "I2C主机命令执行出错，代码: %d", ret);
    return result;
  }
  i2c_cmd_link_delete(cmd);
  i2c_driver_delete(I2C_MASTER_NUM);
  esp_log_buffer_hex_internal("I2C主机,读取结果", data_rd, data_length, ESP_LOG_INFO);
  result.status = ret;
  result.data = data_rd;
  return result;
}

ParseResult ldg_i2c_master_read_data(uint8_t *read_cmd, uint8_t cmd_length, uint16_t data_length)
{
  return ldg_i2c_master_read(0xA0, read_cmd, cmd_length, data_length);
}

ParseResult ldg_i2c_master_write(uint8_t slave_address, uint8_t *write_cmd, uint8_t cmd_length, uint16_t data_length)
{
  esp_log_buffer_hex_internal("I2C主机,写操作", write_cmd, cmd_length, ESP_LOG_INFO);
  ParseResult result;
  result.status = ESP_FAIL;
  esp_err_t ret = ldg_i2c_master_init();
  if (ret != ESP_OK)
  {
    return result;
  }
  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  i2c_master_start(cmd);
  i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, true);
  for (size_t i = 0; i < cmd_length; i++)
  {
    i2c_master_write_byte(cmd, write_cmd[i], true);
  }
  i2c_master_stop(cmd);
  ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
  result.status = ret;
  i2c_cmd_link_delete(cmd);
  if (ret != ESP_OK)
  {
    i2c_driver_delete(I2C_MASTER_NUM);
    ESP_LOGE("I2C主机", "I2C主机命令执行出错，代码: %d", ret);
    return result;
  }
  i2c_driver_delete(I2C_MASTER_NUM);
  return result;
}
